package statisticabusiness.engine;

import java.util.ArrayList;

/**
 ** Implementazione della classe per calcolare la distanza di Minkowski
 * @author Gagliano Turi, Giuffrida Alberto
 */
public class DistMinkowski {
    
    ArrayList<double[][]> matriciSequenziali;
    double[][] distanze;
    private int numVar;    
    double coeffMin;
    ArrayList<int[]> dati;
    
    /**
     * Metodo costruttore<br/>
     * MatriciSequenziali  viene passata come lista vuota e sar&agrave; 
     * quindi inizializzata con le distanze iniziali
     * @param coeffMin      intero che indica il coefficente di Minkowski
     * @param numVar        intero che indica da quante coordinate &egrave; costituita una variabile
     * @param matriciSequenziali    lista delle matrici che si ricavano ad ogni iterazione del metodo
     * @param dati      lista dei dati immessi dall'utente
     */
    public DistMinkowski(double coeffMin, int numVar, ArrayList<double[][]> matriciSequenziali, ArrayList<int[]> dati){
  
        this.matriciSequenziali= matriciSequenziali;
        this.coeffMin = coeffMin;
        this.dati = dati;
        this.numVar = numVar;
        
    }
    
     
    /**
     * Questo metodo crea la matrice delle distanze riempiendo il primo elemento
     * di indice zero di matriciSequenziali
     */
    public void distanzaMinkowski(){
        
        distanze = new double[dati.size()][dati.size()];
        
        double k,t;
        int[] appoggio1, appoggio2;
        
        for(int i=0; i<dati.size(); i++){
            
            //nel for successivo faccio partire j da i+1 cosi riempio solo il triangolo superiore
            for(int j=i; j<dati.size(); j++){   
                
                //nella diagonale metto valori nuli
                if(i==j){
                    distanze[i][j]=0.0;
                    continue;
                }
                //carico negli appoggi due dati alla volta
                appoggio1= dati.get(i);
                appoggio2= dati.get(j);
                k=0.0;
                t=0.0;
                //calcolo la distanza con la formula di Minkowski
                for(int w=0; w<numVar; w++){
                    k = Math.abs(appoggio1[w] - appoggio2[w]);
                    k= Math.pow(k, coeffMin);
                    t=t+k;
                }
                
                distanze[i][j]= (double) Math.pow(t,(1.0/coeffMin));  //metti 1.0 e non 1 per forzare il risultato a reale e no a intero
            }            
        }
        this.completaMatrice(distanze);
        matriciSequenziali.add(distanze);  //carico la matrice delle distanze iniziali come primo elemento della lista
        stampa(distanze);
    }
    
    /**
     * A partire da una triangolare superiore restituisce una triangolare competa
     * con la diagonale nulla
     * @param d  matrice da completare
     */
    public void completaMatrice(double[][] d){
        
        for(int i=1; i<d.length; i++){
            
            for(int j=0; j<i; j++){  
                    d[i][j]=d[j][i];  
            }      
        }
    }
    
    /**
     * Stampa il contenuto di una matrice nella console. <br/>
     * Utile in fase di debug
     * @param d
     */
    public void stampa(double[][] d){
        for(int i=0; i<d.length; i++){
            //nel for successivo faccio partire j da i+1 cosi riempio solo il triangolo superiore
            for(int j=0; j<d.length; j++){   
                System.out.print("[" + d[i][j] + "]");
            }
            System.out.println("");
        }
        System.out.println("fine matrice");
    }    
}
